package cn.demoncat.util.redis.util;

import cn.demoncat.util.lang.ThreadUtil;
import cn.demoncat.util.mybatis.util.TransactionUtil;
import cn.demoncat.util.redis.config.RedisIsolator;
import cn.demoncat.util.redis.entity.RedisLock;
import org.redisson.api.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * Redisson 工具
 *
 * Redis的封装，提供了分布式的Lock锁和集合对象。
 *
 * 1、通过LUA脚本封装命令，保证操作的原子性
 * 2、通过看门狗，间隔30秒延期缓存，防止缓存释放失败造成死锁
 *
 * 注：为了跟踪项目中使用了哪些锁，必须使用RedisLock对象来声明锁的缓存常量
 * 注：为了跟踪项目中使用了哪些键，必须使用RedisKey对象来声明缓存常量
 *
 * @see <a href="https://github.com/redisson/redisson/wiki">文档</a>
 * @see <a href="https://github.com/redisson/redisson">源码</a>
 *
 * @author 延晓磊
 * @since 2021年02月10日
 */
@Component
public class RedissonUtil {

    @Resource
    private RedissonClient redissonClient;
    @Resource
    private RedisIsolator redisIsolator;

    private static final Logger LOG = LoggerFactory.getLogger(RedissonUtil.class);

    /**
     * 获取Redisson Client
     *
     * @return
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public RedissonClient getClient(){
        return redissonClient;
    }

    /* ========================= 分布式锁 =========================== */

    /**
     * 获取Redisson锁
     *
     * @param key
     * @return
     */
    private RLock getLock(String key){
        return getClient().getLock(redisIsolator.getKey(key));
    }

    /**
     * 获取Redisson锁
     *
     * @param key
     * @return
     */
    private RLock getFairLock(String key){
        return getClient().getFairLock(redisIsolator.getKey(key));
    }

    /**
     * 获取Redisson锁
     *
     * @param key
     * @return
     */
    private RReadWriteLock getReadWriteLock(String key){
        return getClient().getReadWriteLock(redisIsolator.getKey(key));
    }

    /**
     * 执行锁操作
     *
     * 场景：A获取锁开始执行 > B未获取锁，阻塞加锁/尝试加锁 > A执行完成，释放锁/锁到期 > B获取锁开始执行
     *
     * 1、阻塞加锁/尝试加锁
     * 2、加锁成功：执行业务，解锁/自动释放锁
     * 2、加锁失败：执行降级处理
     *
     * @param rLock 锁对象
     * @param lock  锁（根据tryLock判断阻塞或尝试）
     * @param success  获取锁后执行的操作
     * @param error   未获取锁的降级处理，为空时直接返回null
     *
     * @return 业务返回结果
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <R>R lock(RLock rLock, RedisLock lock, Supplier<R> success, Supplier<R> error){
        // 加锁
        if (addLock(rLock, lock, lock.isTryLock())) {
            // 加锁成功，执行业务，释放锁
            return lockOperation(rLock, lock, success);
        }else{
            // 加锁失败，执行降级处理
            return error == null ? null : error.get();
        }
    }

    /**
     * 阻塞执行锁操作
     *
     * 场景：A获取锁开始执行 > B未获取锁，阻塞等待 > A执行完成，释放锁/锁到期 > B获取锁开始执行
     *
     * 1、阻塞加锁
     * 2、执行业务
     * 3、解锁/自动释放锁
     *
     * @param rLock 锁对象
     * @param lock  锁（忽略tryLock属性）
     * @param callable  获取锁后执行的操作
     *
     * @return 业务返回结果
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <R>R lock(RLock rLock, RedisLock lock, Supplier<R> callable){
        // 加锁
        addLock(rLock, lock, false);
        // 执行业务，释放锁
        return lockOperation(rLock, lock, callable);
    }

    /**
     * 尝试执行锁操作
     *
     * 场景：A获取锁开始执行 > B未获取锁，放弃执行 > A执行完成，释放锁/锁到期
     *
     * 1、尝试加锁
     * 2、加锁成功：执行业务，解锁/自动释放锁
     * 2、加锁失败：执行降级处理
     *
     * @param rLock 锁对象
     * @param lock  锁（忽略tryLock属性）
     * @param success  获取锁后执行的操作
     * @param error   未获取锁的降级处理，为空时直接返回null
     *
     * @return 是否加锁成功
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <R>R tryLock(RLock rLock, RedisLock lock, Supplier<R> success, Supplier<R> error){
        // 加锁
        if (addLock(rLock, lock, true)) {
            // 加锁成功，执行业务，释放锁
            return lockOperation(rLock, lock, success);
        }else{
            // 加锁失败，执行降级处理
            return error == null ? null : error.get();
        }
    }

    /**
     * 尝试执行锁操作
     *
     * 场景：A获取锁开始执行 > B未获取锁，放弃执行 > A执行完成，释放锁/锁到期
     *
     * 1、尝试加锁，失败返回false
     * 2、执行业务
     * 3、解锁/自动释放锁
     *
     * @param rLock 锁对象
     * @param lock  锁（忽略tryLock属性）
     * @param runnable  获取锁后执行的操作
     *
     * @return 是否加锁成功
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public boolean tryLock(RLock rLock, RedisLock lock, Runnable runnable){
        // 加锁
        if (addLock(rLock, lock, true)) {
            // 加锁成功，执行业务，释放锁
            return lockOperation(rLock, lock, runnable);
        }
        return false;
    }

    /**
     * 可重入锁
     *
     * 可重入锁：表示线程可以重复的"获取+释放"锁
     * 线程饥饿：由于多线程自由竞争，所以会有部分线程一直拿不到锁，即线程饥饿问题
     *
     * 场景：A获取锁开始执行 > B未获取锁，阻塞等待 > A执行完成，释放锁/锁到期 > B获取锁开始执行
     *
     * 1、阻塞加锁/尝试加锁
     * 2、加锁成功：执行业务，解锁/自动释放锁
     * 2、加锁失败：执行降级处理
     *
     * @param lock  锁（根据tryLock判断阻塞或尝试）
     * @param success  获取锁后执行的操作
     * @param error   未获取锁的降级处理，为空时直接返回null
     *
     * @return 业务返回结果
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <R>R lock(RedisLock lock, Supplier<R> success, Supplier<R> error){
        // 获取可重入锁，加锁，执行操作
        return lock(getLock(lock.getKey()), lock, success, error);
    }

    /**
     * 可重入锁 - 阻塞
     *
     * 可重入锁：表示线程可以重复的"获取+释放"锁
     * 线程饥饿：由于多线程自由竞争，所以会有部分线程一直拿不到锁，即线程饥饿问题
     *
     * 场景：A获取锁开始执行 > B未获取锁，阻塞等待 > A执行完成，释放锁/锁到期 > B获取锁开始执行
     *
     * 1、阻塞加锁
     * 2、执行业务
     * 3、解锁/自动释放锁
     *
     * @param lock  锁（忽略tryLock属性）
     * @param callable  获取锁后执行的操作
     * 
     * @return 业务返回结果
     *                  
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <R>R lock(RedisLock lock, Supplier<R> callable){
        // 获取可重入锁，加锁，执行操作
        return lock(getLock(lock.getKey()), lock, callable);
    }

    /**
     * 可重入锁 - 尝试
     *
     * 可重入锁：表示线程可以重复的"获取+释放"锁
     * 线程饥饿：由于多线程自由竞争，所以会有部分线程一直拿不到锁，即线程饥饿问题
     *
     * 场景：A获取锁开始执行 > B未获取锁，放弃执行（降级处理） > A执行完成，释放锁/锁到期
     *
     * 1、尝试加锁
     * 2、加锁成功：执行业务，解锁/自动释放锁
     * 2、加锁失败：执行降级处理
     *
     * @param lock  锁（忽略tryLock属性）
     * @param success  获取锁后执行的操作
     * @param error   未获取锁的降级处理，为空时直接返回null
     *
     * @return 业务返回结果/降级返回结果/null
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <R>R tryLock(RedisLock lock, Supplier<R> success, Supplier<R> error){
        // 获取可重入锁，加锁，执行操作
        return tryLock(getLock(lock.getKey()), lock, success, error);
    }

    /**
     * 可重入锁 - 尝试
     *
     * 可重入锁：表示线程可以重复的"获取+释放"锁
     * 线程饥饿：由于多线程自由竞争，所以会有部分线程一直拿不到锁，即线程饥饿问题
     *
     * 场景：A获取锁开始执行 > B未获取锁，放弃执行 > A执行完成，释放锁/锁到期
     *
     * 1、尝试加锁，失败返回false
     * 2、执行业务
     * 3、解锁/自动释放锁
     *
     * @param lock  锁（忽略tryLock属性）
     * @param runnable  获取锁后执行的操作
     *
     * @return 是否加锁成功
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public boolean tryLock(RedisLock lock, Runnable runnable){
        // 获取可重入锁，加锁，执行操作
        return tryLock(getLock(lock.getKey()), lock, runnable);
    }

    /**
     * 可重入公平锁 - 阻塞
     *
     * 公平锁：按请求锁的顺序排列线程，保证先来先得，可以解决线程饥饿问题，但因为要处理线程排列而性能变低
     *
     * 1、阻塞加锁
     * 2、执行业务
     * 3、解锁/自动释放锁
     *
     * @param lock  锁
     * @param callable  获取锁后执行的操作
     *
     * @return 业务返回结果
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <R>R fairLock(RedisLock lock, Supplier<R> callable){
        // 获取公平锁，加锁，执行操作
        return lock(getFairLock(lock.getKey()), lock, callable);
    }

    /**
     * 可重入公平锁 - 尝试
     *
     * 公平锁：按请求锁的顺序排列线程，保证先来先得，可以解决线程饥饿问题，但因为要处理线程排列而性能变低
     *
     * 1、尝试加锁，失败返回false
     * 2、执行业务
     * 3、解锁/自动释放锁
     *
     * @param lock  锁
     * @param runnable  获取锁后执行的操作
     *
     * @return 是否获取成功
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public boolean tryFairLock(RedisLock lock, Runnable runnable){
        // 获取公平锁，加锁，执行操作
        return tryLock(getFairLock(lock.getKey()), lock, runnable);
    }

    /**
     * 可重入读写锁 - 读，阻塞
     *
     * 读写锁：维护只读和只写的锁操作，通过读写分离来提升并发效率
     * 读+读：无锁，并发
     * 写+读：写释放后，才可以读
     * 写+写：有锁
     * 读+写：读全部完成再写，写完成后才能读
     *
     * 1、阻塞加锁
     * 2、执行业务
     * 3、解锁/自动释放锁
     *
     * @param lock  锁
     * @param callable  获取锁后执行的操作
     *
     * @return 业务返回结果
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <R>R readLock(RedisLock lock, Supplier<R> callable){
        // 获取读写锁，获取读锁，加锁，执行操作
        return lock(getReadWriteLock(lock.getKey()).readLock(), lock, callable);
    }

    /**
     * 可重入读写锁 - 读，尝试
     *
     * 读写锁：维护只读和只写的锁操作，通过读写分离来提升并发效率
     * 读+读：无锁，并发
     * 写+读：写释放后，才可以读
     * 写+写：有锁
     * 读+写：读全部完成再写，写完成后才能读
     *
     * 1、尝试加锁，失败返回false
     * 2、执行业务
     * 3、解锁/自动释放锁
     *
     * @param lock  锁
     * @param runnable  获取锁后执行的操作
     *
     * @return 是否获取成功
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public boolean tryReadLock(RedisLock lock, Runnable runnable){
        // 获取读写锁，获取读锁，加锁，执行操作
        return tryLock(getReadWriteLock(lock.getKey()).readLock(), lock, runnable);
    }

    /**
     * 可重入读写锁 - 写，阻塞
     *
     * 读写锁：维护只读和只写的锁操作，通过读写分离来提升并发效率
     * 读+读：无锁，并发
     * 写+读：写释放后，才可以读
     * 写+写：有锁
     * 读+写：读全部完成再写，写完成后才能读
     *
     * 1、尝试加锁，失败返回false
     * 2、执行业务
     * 3、解锁/自动释放锁
     *
     * @param lock  锁
     * @param callable  获取锁后执行的操作
     *
     * @return 业务返回结果
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <R>R writeLock(RedisLock lock, Supplier<R> callable){
        // 获取读写锁，获取写锁，加锁，执行操作
        return lock(getReadWriteLock(lock.getKey()).writeLock(), lock, callable);
    }

    /**
     * 可重入读写锁 - 写，尝试
     *
     * 读写锁：维护只读和只写的锁操作，通过读写分离来提升并发效率
     * 读+读：无锁，并发
     * 写+读：写释放后，才可以读
     * 写+写：有锁
     * 读+写：读全部完成再写，写完成后才能读
     *
     * 1、尝试加锁，失败返回false
     * 2、执行业务
     * 3、解锁/自动释放锁
     *
     * @param lock  锁
     * @param runnable  获取锁后执行的操作
     *
     * @return 是否获取成功
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public boolean tryWriteLock(RedisLock lock, Runnable runnable){
        // 获取读写锁，获取写锁，加锁，执行操作
        return tryLock(getReadWriteLock(lock.getKey()).writeLock(), lock, runnable);
    }

    /**
     * 获取闭锁
     *
     * @param key
     * @return
     */
    private RCountDownLatch getCountDownLatch(String key){
        return getClient().getCountDownLatch(redisIsolator.getKey(key));
    }

    /**
     * 设置闭锁（倒数计数器）
     *
     * 1、当前线程进入阻塞
     * 2、其它线程执行delCountDownLatch方法count次后，唤醒当前线程
     *
     * @param lock  锁
     * @param count 计数
     *
     * @return  是否加锁成功（成功时阻塞等待）
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public boolean countDownLatch(RedisLock lock, int count){
        // 获取闭锁
        RCountDownLatch latch = getCountDownLatch(lock.getKey());
        // 计数
        if (latch.trySetCount(count)) {
            try {
                // 等待
                if (lock.getAwaitTime() == 0) {
                    // 永久
                    latch.await();
                }else{
                    // 限时
                    latch.await(lock.getAwaitTime(), TimeUnit.SECONDS);
                }
            } catch (InterruptedException e) {
                // 线程中断
                threadInterrupt(lock);
            }
            return true;
        }
        return false;
    }

    /**
     * 释放闭锁（倒数计数）
     *
     * @param lock  锁
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public void countDown(RedisLock lock){
        // 获取闭锁
        RCountDownLatch latch = getCountDownLatch(lock.getKey());
        // 计数
        if (lock.isTx()) {
            // 事务回完
            TransactionUtil.afterCompletion(status -> {
                latch.countDown();
                if (status == 2) {
                    LOG.info("因事务回滚而释放锁【{}】", lock.getKey());
                }
            });
        }else{
            latch.countDown();
        }
    }

    /**
     * 获取信号量（共享锁，并发限制）
     *
     * 1、设置、添加信号
     * 2、多线程获取信号，信号为0时无法获取（并行数量限制）
     *
     * 判断 semaphore.isExists()
     * 删除 semaphore.delete()
     * 查看配置信号数 semaphore.drainPermits()
     * 查看可用信号数 semaphore.availablePermits()
     * 设置信息 semaphore.trySetPermits(count)
     * 添加信号 semaphore.addPermits(count)
     *
     * @param name
     *
     * @return
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public RSemaphore getSemaphore(String name){
        return getClient().getSemaphore(redisIsolator.getKey(name));
    }

    /**
     * 获取信号量（共享锁，并发限制）
     *
     * @param lock
     *
     * @return
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public RSemaphore getSemaphore(RedisLock lock){
        return getSemaphore(lock.getKey());
    }

    /**
     * 获取信号量 - 阻塞
     *
     * @param lock  锁
     * @param count 获取数
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public void acquireSemaphore(RedisLock lock, int count){
        // 获取信号量
        RSemaphore semaphore = getSemaphore(lock);
        try {
            // 获取信号
            semaphore.acquire(count);
        } catch (InterruptedException e) {
            // 线程中断
            threadInterrupt(lock);
        }
    }

    /**
     * 获取信号量 - 阻塞，获取1个信号
     *
     * @param lock  锁
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public void acquireSemaphore(RedisLock lock){
        acquireSemaphore(lock, 1);
    }

    /**
     * 获取信号量 - 尝试
     *
     * @param lock  锁
     * @param count 获取数
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public boolean tryAcquireSemaphore(RedisLock lock, int count){
        // 获取信号量
        RSemaphore semaphore = getSemaphore(lock);
        // 获取信号
        if (lock.getTryTime() == 0) {
            // 尝试1次
            return semaphore.tryAcquire(count);
        }else{
            // 尝试n秒
            try {
                return semaphore.tryAcquire(count, lock.getTryTime(), TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                // 线程中断
                threadInterrupt(lock);
            }
        }
        return false;
    }

    /**
     * 获取信号量 - 尝试，获取1个信号
     *
     * @param lock  锁
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public boolean tryAcquireSemaphore(RedisLock lock){
        return tryAcquireSemaphore(lock, 1);
    }

    /**
     * 释放信号量
     *
     * @param lock  锁
     * @param count 释放数
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public void releaseSemaphore(RedisLock lock, int count){
        // 获取信号量
        RSemaphore semaphore = getSemaphore(lock);
        // 计数
        if (lock.isTx()) {
            // 事务回完
            TransactionUtil.afterCompletion(status -> {
                semaphore.release();
                if (status == 2) {
                    LOG.info("因事务回滚而释放锁【{}】", lock.getKey());
                }
            });
        }else{
            semaphore.release();
        }
    }

    /**
     * 释放信号量 - 释放1个信号
     *
     * @param lock  锁
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public void releaseSemaphore(RedisLock lock){
        releaseSemaphore(lock, 1);
    }

    /**
     * 获取限流器
     *
     * @param key
     * @return
     */
    private RRateLimiter getRateLimiter(String key){
        return getClient().getRateLimiter(redisIsolator.getKey(key));
    }

    /**
     * 添加限流器
     *
     * 1、设置限流量器，指定时间段内的流量数（如果未设置，封装在获取时设置）
     * 2、多线程获取流量，信号为0时无法获取（并行数量限制），只能等待下个时间段再请求
     *
     * @param name
     * @param seconds   每个时间段的秒数
     * @param count     每个时间段的放行数
     *
     * @return
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public void addLimiter(String name, long seconds, long count){
        // 获取限流器
        RRateLimiter limiter = getRateLimiter(name);
        // 设置限流
        limiter.setRate(RateType.OVERALL, count, seconds, RateIntervalUnit.SECONDS);
    }

    /**
     * 删除限流器
     *
     * @param name
     *
     * @author 延晓磊
     * @since 2021年02月13日
     */
    public void delLimiter(String name){
        getRateLimiter(name).delete();
    }

    /**
     * 获取流量 - 阻塞
     *
     * @param name  限流器
     * @param num   获取数
     * @param seconds   每个时间段的秒数
     * @param count     每个时间段的放行数
     * @return
     */
    public void acquireLimiter(String name, int num, long seconds, long count){
        // 获取限流器
        RRateLimiter limiter = getRateLimiter(name);
        if (!limiter.isExists()) {
            limiter.trySetRate(RateType.OVERALL, count, seconds, RateIntervalUnit.SECONDS);
        }
        // 获取流量
        limiter.acquire(num);
    }

    /**
     * 获取流量 - 阻塞，获取1个
     *
     * @param name  限流器
     * @param seconds   每个时间段的秒数
     * @param count     每个时间段的放行数
     * @return
     */
    public void acquireLimiter(String name, long seconds, long count){
        acquireLimiter(name, 1, seconds, count);
    }

    /**
     * 获取流量 - 尝试
     *
     * @param name  限流器
     * @param num   获取数
     * @param seconds   每个时间段的秒数
     * @param count     每个时间段的放行数
     * @return
     */
    public boolean tryAcquireLimiter(String name, int num, long seconds, long count){
        // 获取限流器
        RRateLimiter limiter = getRateLimiter(name);
        if (!limiter.isExists()) {
            limiter.trySetRate(RateType.OVERALL, count, seconds, RateIntervalUnit.SECONDS);
        }
        // 获取流量
        return limiter.tryAcquire(num);
    }

    /**
     * 获取流量 - 尝试，获取1个
     *
     * @param name  限流器
     * @param seconds   每个时间段的秒数
     * @param count     每个时间段的放行数
     * @return
     */
    public boolean tryAcquireLimiter(String name, long seconds, long count){
        return tryAcquireLimiter(name, 1, seconds, count);
    }

    /* ========================= 分布式集合 =========================== */

    /**
     * 获取Redis Keys
     *
     * 总数 keys.count()
     * 删除 keys.deleteByPattern("*")
     * 查找 keys.getKeysByPattern("*")
     *
     * @return
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public RKeys keys(){
        return getClient().getKeys();
    }

    /**
     * 获取Map
     *
     * 1、实现了ConcurrentMap接口
     * 2、保持元素的插入顺序
     *
     * @param name
     * @return
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <K,V>RMap<K,V> map(String name){
        return getClient().getMap(redisIsolator.getKey(name));
    }

    /**
     * 获取Set
     *
     * 1、实现了Set接口
     *
     * @param name
     * @return
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <V>RSet<V> set(String name){
        return getClient().getSet(redisIsolator.getKey(name));
    }

    /**
     * 获取SortedSet
     *
     * 1、实现了SortedSet接口
     * 2、通过比较器维护顺序
     *
     * 设置比较器 set.trySetComparator(cp)
     *
     * @param name
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <V> RSortedSet<V> sortedSet(String name){
        return getClient().getSortedSet(redisIsolator.getKey(name));
    }

    /**
     * 获取ScoredSortedSet
     *
     * 1、实现了SortedSet接口
     * 2、通过score维护顺序
     *
     * @param name
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <V> RScoredSortedSet<V> scoredSortedSet(String name){
        return getClient().getScoredSortedSet(redisIsolator.getKey(name));
    }

    /**
     * 获取LexSortedSet
     *
     * 1、实现了SortedSet[String]接口
     * 2、通过字典顺序维护顺序
     *
     * @param name
     * @return
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public RLexSortedSet lexSortedSet(String name){
        return getClient().getLexSortedSet(redisIsolator.getKey(name));
    }

    /**
     * 获取List
     *
     * 1、实现了List接口
     * 2、保持元素的插入顺序
     *
     * @param name
     * @return
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <V> RList<V> list(String name){
        return getClient().getList(redisIsolator.getKey(name));
    }

    /**
     * 获取Queue - 无界队列
     *
     * 1、实现了Queue接口
     * 2、以FIFO(先进先出)的方式排序元素，即加入队列、获取队首
     *
     * 加入队尾 queue.add(e)        容量不足抛异常
     * 加入队尾 queue.offer(e)      容量不足返回false
     * 查看队首 queue.peek()        容量为空返回null
     * 查看队首 queue.element()     容量为空抛异常
     * 移除队首 queue.poll()        容量为空返回null
     * 移除队首 queue.remove()      容量为空抛异常
     *
     * @param name
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <V> RQueue<V> queue(String name){
        return getClient().getQueue(redisIsolator.getKey(name));
    }

    /**
     * 获取Blocking Queue - 阻塞无界队列
     *
     * 1、实现了BlockingQueue接口
     * 2、以FIFO(先进先出)的方式排序元素，即加入队列、获取队首
     *
     * 加入队尾 queue.put(e)    容量不足时阻塞
     * 移除队首 queue.take()    容量为空时阻塞
     *
     * @param name
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <V> RBlockingQueue<V> blockingQueue(String name) {
        return getClient().getBlockingQueue(redisIsolator.getKey(name));
    }

    /**
     * 获取Bounded Blocking Queue - 阻塞有界队列
     *
     * 1、实现了BlockingQueue接口
     * 2、以FIFO(先进先出)的方式排序元素，即加入队列、获取队首
     *
     * 加入队尾 queue.put(e)    容量不足时阻塞
     * 移除队首 queue.take()    容量为空时阻塞
     * 设置容量 queue.trySetCapacity(n) 设置成功返回true，已设置返回false
     *
     * @param name
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <V> RBoundedBlockingQueue<V> boundedBlockingQueue(String name) {
        return getClient().getBoundedBlockingQueue(redisIsolator.getKey(name));
    }

    /**
     * 加入阻塞队列：容量不足时阻塞，线程中断时忽略
     *
     * @param queue 阻塞队列
     * @param v     元素
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <V>void putBlockingQueue(RBlockingQueue<V> queue, V v){
        try {
            // 加入队列，容量不足时阻塞
            queue.put(v);
        } catch (InterruptedException e) {
            // 线程中断
            threadInterrupt(queue.getName());
        }
    }

    /**
     * 获取阻塞队列：容量为空时阻塞，线程中断返回null
     *
     * @param queue 阻塞队列
     * @return
     *
     * @author 延晓磊
     * @since 2021年02月10日
     */
    public <V>V takeBlockingQueue(RBlockingQueue<V> queue){
        try {
            // 加入队列，容量不足时阻塞
            return queue.take();
        } catch (InterruptedException e) {
            // 线程中断
            threadInterrupt(queue.getName());
            return null;
        }
    }

    /**
     * 线程中断处理
     *
     * @param data
     * 
     * @author 延晓磊
     * @since 2021年02月13日
     */
    private static void threadInterrupt(Object data){
        // 自我中断
        ThreadUtil.interrupt();
        // 记录日志
        LOG.warn("线程中断：" + data);
    }

    /**
     * 加锁
     *
     * @param rLock
     * @param lock
     * @param isTryLock 是否为尝试加锁（忽略lock.tryLock）
     * @return
     *
     * @author 延晓磊
     * @since 2021年02月13日
     */
    public boolean addLock(RLock rLock, RedisLock lock, boolean isTryLock){
        if (isTryLock) {
            // 尝试加锁
            if (lock.getExp() == 0) {
                // 主动释放的锁（顺序执行）
                if (lock.getTryTime() == 0) {
                    // 尝试1次
                    return rLock.tryLock();
                }else{
                    // 尝试n秒
                    try {
                        return rLock.tryLock(lock.getTryTime(), TimeUnit.SECONDS);
                    } catch (InterruptedException e) {
                        // 线程中断
                        threadInterrupt(lock);
                        return false;
                    }
                }
            }else{
                // 自动到期的锁（间隔执行）
                try {
                    if (lock.getTryTime() == 0) {
                        // 尝试1次
                        return rLock.tryLock(-1, lock.getExp(), TimeUnit.SECONDS);
                    }else{
                        // 尝试n秒
                        return rLock.tryLock(lock.getTryTime(), lock.getExp(), TimeUnit.SECONDS);
                    }
                } catch (InterruptedException e) {
                    // 线程中断
                    threadInterrupt(lock);
                    return false;
                }
            }
        }else{
            // 阻塞加锁
            if (lock.getExp() == 0) {
                // 主动释放的锁（顺序执行）
                rLock.lock();
            }else{
                // 自动到期的锁（间隔执行）
                rLock.lock(lock.getExp(), TimeUnit.SECONDS);
            }
            return true;
        }
    }

    /**
     * 锁操作 - 有返回
     * 
     * @param rLock
     * @param lock
     * @param callable
     * @return
     * 
     * @author 延晓磊
     * @since 2021年02月13日
     */
    private static <R>R lockOperation(RLock rLock, RedisLock lock, Supplier<R> callable){
        try {
            // 执行操作
            R r = callable.get();
            // 释放锁
            if (lock.getExp() == 0) {
                if (lock.isTx()) {
                    // 事务回完
                    TransactionUtil.afterCompletion(status -> {
                        unlock(rLock);
                        if (status == 2) {
                            LOG.info("因事务回滚而释放锁【{}】", lock.getKey());
                        }
                    });
                } else {
                    unlock(rLock);
                }
            }
            return r;
        }catch (RuntimeException re){
            LOG.warn("加锁业务执行异常【{}】", lock.getKey(), re);
            // 执行失败，释放锁
            unlock(rLock);
            // 返回运行异常
            throw re;
        }
    }

    /**
     * 锁操作 - 无返回
     *
     * @param rLock
     * @param lock
     * @param runnable
     * @return true
     *
     * @author 延晓磊
     * @since 2021年02月13日
     */
    private static boolean lockOperation(RLock rLock, RedisLock lock, Runnable runnable){
        try {
            // 执行操作
            runnable.run();
            // 释放锁
            if (lock.getExp() == 0) {
                if (lock.isTx()) {
                    // 事务回完
                    TransactionUtil.afterCompletion(status -> {
                        unlock(rLock);
                        if (status == 2) {
                            LOG.info("因事务回滚而释放锁【{}】", lock.getKey());
                        }
                    });
                } else {
                    unlock(rLock);
                }
            }
            return true;
        }catch (RuntimeException re){
            LOG.warn("加锁业务执行异常【{}】", lock.getKey(), re);
            // 执行失败，释放锁
            unlock(rLock);
            // 返回运行异常
            throw re;
        }
    }

    /**
     * 解锁
     *
     * 问题：IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: * thread-id: 88
     * 原因：只有加锁成功才需要解锁；只能解自己加的锁
     * 解决：解锁前进行判断 || 强制释放锁
     *
     * @param lock
     *
     * @author 延晓磊
     * @since 2022年07月27日
     */
    private static void unlock(RLock lock){
        if (lock.isLocked() && lock.isHeldByCurrentThread()) {
            // 已加锁 && 由当前线程持有
            lock.unlock();
        }else{
            // 强制解锁
            lock.forceUnlock();
        }
    }
}
